home *** CD-ROM | disk | FTP | other *** search
- /*
-
- Copyright (C) 1995
- Free Software Foundation, Inc.
-
- This file is part of GNU cfengine - written and maintained
- by Mark Burgess, Dept of Computing and Engineering, Oslo College,
- Dept. of Theoretical physics, University of Oslo
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
- */
-
-
- /*******************************************************************/
- /* */
- /* File Image copying */
- /* */
- /*******************************************************************/
-
- #define INET 1
-
- #include "cf.defs.h"
- #include "cf.extern.h"
-
- /*********************************************************************/
- /* Level 1 */
- /*********************************************************************/
-
- RecursiveImage(ip,from,to,maxrecurse)
-
- struct Image *ip;
- char *from, *to;
- int maxrecurse;
-
- { struct stat statbuf, deststatbuf;
- char newfrom[bufsize];
- char newto[bufsize];
- int save_uid, save_gid;
- struct Item *namecache = NULL;
- struct cfdirent *dirp;
- CFDIR *dirh;
-
- if (maxrecurse == 0) /* reached depth limit */
- {
- Debug2("MAXRECURSE ran out, quitting at level %s with endlist = %d\n",from,ip->next);
- return;
- }
-
- Debug2("RecursiveImage(%s,lev=%d,next=%d)\n",from,maxrecurse,ip->next);
-
- if (IgnoreFile(from,"",ip->ignores))
- {
- Verbose("Ignoring directory %s\n",from);
- return;
- }
-
- if (strlen(from) == 0) /* Check for root dir */
- {
- from = "/";
- }
-
- /* Check that dest dir exists before starting */
-
- strcpy(newto,to);
- AddSlash(newto);
-
- if (! MakeDirectoriesFor(newto))
- {
- sprintf(OUTPUT,"Unable to make directory for %s in copy: %s to %s\n",newto,ip->path,ip->destination);
- CfLog(cferror,OUTPUT,"");
- return;
- }
-
- if ((dirh = cfopendir(from,ip)) == NULL)
- {
- sprintf(OUTPUT,"copy can't open directory [%s]\n",from);
- CfLog(cferror,OUTPUT,"");
- return;
- }
-
- for (dirp = cfreaddir(dirh,ip); dirp != NULL; dirp = cfreaddir(dirh,ip))
- {
- if (!SensibleFile(dirp->d_name,from,ip))
- {
- continue;
- }
-
- if (ip->purge == 'y') /* Do not purge this file */
- {
- AppendItem(&namecache,dirp->d_name,NULL);
- }
-
- if (IgnoreFile(from,dirp->d_name,ip->ignores))
- {
- continue;
- }
-
- strcpy(newfrom,from); /* Assemble pathname */
- AddSlash(newfrom);
- strcpy(newto,to);
- AddSlash(newto);
-
- if (BufferOverflow(newfrom,dirp->d_name))
- {
- printf(" culprit: RecursiveImage\n");
- cfclosedir(dirh);
- return;
- }
-
- strcat(newfrom,dirp->d_name);
-
- if (BufferOverflow(newto,dirp->d_name))
- {
- printf(" culprit: RecursiveImage\n");
- cfclosedir(dirh);
- return;
- }
-
- strcat(newto,dirp->d_name);
-
- if (TRAVLINKS || ip->linktype == 'n')
- {
- if (cfstat(newfrom,&statbuf,ip) == -1)
- {
- Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom);
- continue;
- }
- }
- else
- {
- if (cflstat(newfrom,&statbuf,ip) == -1)
- {
- Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom);
- continue;
- }
- }
-
- if (!S_ISDIR(statbuf.st_mode) && IgnoredOrExcluded(image,dirp->d_name,ip->inclusions,ip->exclusions))
- {
- continue;
- }
-
- if (S_ISDIR(statbuf.st_mode))
- {
- bzero(&deststatbuf,sizeof(struct stat));
- save_uid = (ip->uid)->uid;
- save_gid = (ip->gid)->gid;
-
- if ((ip->uid)->uid == (uid_t)-1) /* Preserve uid and gid */
- {
- (ip->uid)->uid = statbuf.st_uid;
- }
-
- if ((ip->gid)->gid == (gid_t)-1)
- {
- (ip->gid)->gid = statbuf.st_gid;
- }
-
- if (stat(newto,&deststatbuf) == -1)
- {
- mkdir(newto,statbuf.st_mode);
- }
-
- CheckCopiedFile(newto,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&statbuf,NULL,ip->acl_aliases);
-
- (ip->uid)->uid = save_uid;
- (ip->gid)->gid = save_gid;
-
- RecursiveImage(ip,newfrom,newto,maxrecurse-1);
- }
- else
- {
- CheckImage(newfrom,newto,ip);
- }
- }
-
- if (ip->purge == 'y')
- {
- PurgeFiles(namecache,to);
- DeleteItemList(namecache);
- }
-
- DeleteCompressedArray(ip->inode_cache);
-
- ip->inode_cache = NULL;
-
- cfclosedir(dirh);
- }
-
- /*********************************************************************/
-
- CheckHomeImages(ip)
-
- struct Image *ip;
-
- { CFDIR *dirh, *dirh2;
- struct cfdirent *dirp, *dirp2;
- char *ReadLastNode(), username[maxvarsize];
- char homedir[bufsize],dest[bufsize];
- struct passwd *pw;
- struct stat statbuf;
- struct Item *itp;
- int request_uid = ip->uid->uid; /* save if -1 */
-
- if (!MountPathDefined())
- {
- printf("%s: mountpattern is undefined\n",VPREFIX);
- return;
- }
-
- if (cfstat(ip->path,&statbuf,ip))
- {
- sprintf(OUTPUT,"Master file %s doesn't exist for copying\n",ip->path);
- CfLog(cferror,OUTPUT,"");
- return;
- }
-
- for (itp = VMOUNTLIST; itp != NULL; itp=itp->next)
- {
- if (IsExcluded(itp->classes))
- {
- continue;
- }
-
- if ((dirh = cfopendir(itp->name,ip)) == NULL)
- {
- sprintf(OUTPUT,"Can't open directory %s\n",itp->name);
- CfLog(cferror,OUTPUT,"cfopendir");
- return;
- }
-
- for (dirp = cfreaddir(dirh,ip); dirp != NULL; dirp = cfreaddir(dirh,ip))
- {
- if (!SensibleFile(dirp->d_name,itp->name,ip))
- {
- continue;
- }
-
- strcpy(homedir,itp->name);
- AddSlash(homedir);
- strcat(homedir,dirp->d_name);
-
- if (! IsHomeDir(homedir))
- {
- continue;
- }
-
- if ((dirh2 = cfopendir(homedir,ip)) == NULL)
- {
- sprintf(OUTPUT,"Can't open directory %s\n",homedir);
- CfLog(cferror,OUTPUT,"cfopendir");
- return;
- }
-
- for (dirp2 = cfreaddir(dirh2,ip); dirp2 != NULL; dirp2 = cfreaddir(dirh2,ip))
- {
- if (!SensibleFile(dirp2->d_name,homedir,ip))
- {
- continue;
- }
-
- strcpy(username,dirp2->d_name);
- strcpy(dest,homedir);
- AddSlash(dest);
- strcat(dest,dirp2->d_name);
-
- if (strlen(ip->destination) > 4)
- {
- AddSlash(dest);
- if (strlen(ip->destination) < 6)
- {
- sprintf(OUTPUT,"Error in home/copy to %s",ip->destination);
- CfLog(cferror,OUTPUT,"");
- return;
- }
- else
- {
- strcat(dest,(ip->destination)+strlen("home/"));
- }
- }
-
- if (request_uid == -1)
- {
- if ((pw = getpwnam(username)) == NULL)
- {
- Debug2("cfengine: directory corresponds to no user %s - ignoring\n",username);
- continue;
- }
- else
- {
- Debug2("(Setting user id to %s)\n",username);
- }
-
- ip->uid->uid = pw->pw_uid;
- }
-
- CheckImage(ip->path,dest,ip);
- }
- cfclosedir(dirh2);
- }
- cfclosedir(dirh);
- }
- }
-
- /*********************************************************************/
- /* Level 2 */
- /*********************************************************************/
-
- CheckImage(source,destination,ip)
-
- char *source;
- char *destination;
- struct Image *ip;
-
- { CFDIR *dirh;
- char sourcefile[bufsize];
- char sourcedir[bufsize];
- char destdir[bufsize];
- char destfile[bufsize];
- struct stat sourcestatbuf, deststatbuf;
- struct cfdirent *dirp;
- int save_uid, save_gid, found;
-
- Debug2("CheckImage (source=%s destination=%s)\n",source,destination);
-
- if (ip->linktype == 'n')
- {
- found = cfstat(source,&sourcestatbuf,ip);
- }
- else
- {
- found = cflstat(source,&sourcestatbuf,ip);
- }
-
- if (found == -1)
- {
- sprintf(OUTPUT,"Can't stat %s\n",source);
- CfLog(cferror,OUTPUT,"");
- FlushClientCache(ip);
- return;
- }
-
- if (sourcestatbuf.st_nlink > 1) /* Preserve hard link structure when copying */
- {
- RegisterHardLink(sourcestatbuf.st_ino,destination,ip);
- }
-
- save_uid = (ip->uid)->uid;
- save_gid = (ip->gid)->gid;
-
- if ((ip->uid)->uid == (uid_t)-1) /* Preserve uid and gid */
- {
- (ip->uid)->uid = sourcestatbuf.st_uid;
- }
-
- if ((ip->gid)->gid == (gid_t)-1)
- {
- (ip->gid)->gid = sourcestatbuf.st_gid;
- }
-
- if (S_ISDIR(sourcestatbuf.st_mode))
- {
- strcpy(sourcedir,source);
- AddSlash(sourcedir);
- strcpy(destdir,destination);
- AddSlash(destdir);
-
- if ((dirh = cfopendir(sourcedir,ip)) == NULL)
- {
- sprintf(OUTPUT,"%s: Can't open directory %s\n",VPREFIX,sourcedir);
- CfLog(cferror,OUTPUT,"opendir");
- FlushClientCache(ip);
- (ip->uid)->uid = save_uid;
- (ip->gid)->gid = save_gid;
- return;
- }
-
- /* Now check any overrides */
-
- CheckCopiedFile(destdir,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
-
- for (dirp = cfreaddir(dirh,ip); dirp != NULL; dirp = cfreaddir(dirh,ip))
- {
- if (!SensibleFile(dirp->d_name,sourcedir,ip))
- {
- continue;
- }
-
- strcpy(sourcefile, sourcedir);
-
- if (BufferOverflow(sourcefile,dirp->d_name))
- {
- FatalError("Culprit: CheckImage");
- }
-
- strcat(sourcefile, dirp->d_name);
- strcpy(destfile, destdir);
-
- if (BufferOverflow(destfile,dirp->d_name))
- {
- FatalError("Culprit: CheckImage");
- }
-
- strcat(destfile, dirp->d_name);
-
- if (cflstat(sourcefile,&sourcestatbuf,ip) == -1)
- {
- printf("%s: Can't stat %s\n",VPREFIX,sourcefile);
- FlushClientCache(ip);
- (ip->uid)->uid = save_uid;
- (ip->gid)->gid = save_gid;
- return;
- }
-
- ImageCopy(sourcefile,destfile,sourcestatbuf,ip);
- }
-
- cfclosedir(dirh);
- FlushClientCache(ip);
- (ip->uid)->uid = save_uid;
- (ip->gid)->gid = save_gid;
- return;
- }
-
- strcpy(sourcefile,source);
- strcpy(destfile,destination);
-
- ImageCopy(sourcefile,destfile,sourcestatbuf,ip);
- (ip->uid)->uid = save_uid;
- (ip->gid)->gid = save_gid;
- FlushClientCache(ip);
- }
-
- /*********************************************************************/
-
- PurgeFiles(filelist,directory)
-
- struct Item *filelist;
- char *directory;
-
- { DIR *dirh;
- struct stat statbuf;
- struct dirent *dirp;
- char filename[bufsize];
-
- Debug("PurgeFiles(%s)\n",directory);
-
- /* If we purge with no authentication we wipe out EVERYTHING */
-
- if (!AUTHENTICATED)
- {
- Verbose("Not purging %s - no verified contact with server\n",directory);
- return;
- }
-
- if ((dirh = opendir(directory)) == NULL)
- {
- sprintf(OUTPUT,"Can't open directory %s\n",directory);
- CfLog(cferror,OUTPUT,"cfopendir");
- return;
- }
-
- for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh))
- {
- if (!SensibleFile(dirp->d_name,directory,NULL))
- {
- continue;
- }
-
- if (! IsItemIn(filelist,dirp->d_name))
- {
- strcpy(filename,directory);
- AddSlash(filename);
- strcat(filename,dirp->d_name);
-
- if (DONTDO)
- {
- printf("%s: Need to purge %s from copy dest directory\n",filename);
- }
- else
- {
- sprintf(OUTPUT,"Purging %s in copy dest directory\n",filename);
- CfLog(cfsilent,OUTPUT,"");
-
- if (unlink(filename) == -1)
- {
- if (stat(filename,&statbuf) == -1)
- {
- sprintf(OUTPUT,"Couldn't stat %s while purging\n",filename);
- CfLog(cfverbose,OUTPUT,"stat");
- }
-
- if (S_ISDIR(statbuf.st_mode))
- {
- struct Tidy tp;
- struct TidyPattern tpat;
-
- tp.recurse;
- tp.tidylist = &tpat;
- tp.next = NULL;
- tp.path = filename;
-
- tpat.recurse = INFINITERECURSE;
- tpat.age = 0;
- tpat.size = 0;
- tpat.pattern = strdup("*");
- tpat.classes = strdup("any");;
- tpat.defines = NULL;
- tpat.dirlinks = 't';
- tpat.rmdirs = 't';
- tpat.searchtype = 'a';
- tpat.log = 'd';
- tpat.inform = 'd';
- tpat.next = NULL;
- RecursiveTidySpecialArea(filename,&tp,INFINITERECURSE);
- free(tpat.pattern);
- free(tpat.classes);
-
- if (rmdir(filename) == -1)
- {
- sprintf(OUTPUT,"Couldn't remove directory %s while purging\n",filename);
- CfLog(cfverbose,OUTPUT,"rmdir");
- }
- continue;
- }
-
- sprintf(OUTPUT,"Couldn't unlink %s while purging\n",filename);
- CfLog(cfverbose,OUTPUT,"");
- }
- }
- }
- }
-
- closedir(dirh);
- }
-
-
- /*********************************************************************/
- /* Level 3 */
- /*********************************************************************/
-
- ImageCopy(sourcefile,destfile,sourcestatbuf,ip)
-
- char *sourcefile;
- char *destfile;
- struct stat sourcestatbuf;
- struct Image *ip;
-
- { char linkbuf[bufsize], *lastnode;
- struct stat deststatbuf;
- struct Link empty;
- int succeed, i, silent = false, enforcelinks;
- mode_t srcmode = sourcestatbuf.st_mode;
- int ok_to_copy, found;
-
- Debug2("ImageCopy(%s,%s,+%o,-%o)\n",sourcefile,destfile,ip->plus,ip->minus);
-
- empty.defines = NULL;
-
- if (IgnoredOrExcluded(image,sourcefile,ip->inclusions,ip->exclusions))
- {
- return;
- }
-
- if (ip->linktype != 'n')
- {
- if (IsWildItemIn(VLINKCOPIES,lastnode) || IsWildItemIn(ip->symlink,lastnode))
- {
- Verbose("cfengine: copy item %s marked for linking instead\n",sourcefile);
- enforcelinks = ENFORCELINKS;
- ENFORCELINKS = true;
-
- switch (ip->linktype)
- {
- case 's':
- succeed = LinkFiles(destfile,sourcefile,NULL,NULL,NULL,true,&empty);
- break;
- case 'r':
- succeed = RelativeLink(destfile,sourcefile,NULL,NULL,NULL,true,&empty);
- break;
- case 'a':
- succeed = AbsoluteLink(destfile,sourcefile,NULL,NULL,NULL,true,&empty);
- break;
- default:
- printf("%s: internal error, link type was [%c] in ImageCopy\n",VPREFIX,ip->linktype);
- return;
- }
-
- if (succeed)
- {
- ENFORCELINKS = enforcelinks;
- lstat(destfile,&deststatbuf);
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
- }
-
- return;
- }
- }
-
- if (strcmp(ip->action,"silent") == 0)
- {
- silent = true;
- }
-
- bzero(linkbuf,bufsize);
-
- found = lstat(destfile,&deststatbuf);
-
- if (found != -1)
- {
- if (S_ISLNK(deststatbuf.st_mode) && (ip->linktype == 'n'))
- {
- if (unlink(destfile) == -1)
- {
- sprintf(OUTPUT,"Couldn't remove link",destfile);
- CfLog(cferror,OUTPUT,"unlink");
- return;
- }
- Verbose("Removing old symbolic link %s to make way for copy\n",destfile);
- found = -1;
- }
- }
-
- if (found == -1)
- {
- if (strcmp(ip->action,"warn") == 0)
- {
- sprintf(OUTPUT,"Image file %s is non-existent\n",destfile);
- CfLog(cfsilent,OUTPUT,"");
- sprintf(OUTPUT,"(should be copy of %s)\n",sourcefile);
- CfLog(cfsilent,OUTPUT,"");
- return;
- }
-
- if (S_ISREG(srcmode))
- {
- sprintf(OUTPUT,"%s wasn't at destination",destfile);
- CfLog(cfverbose,OUTPUT,"");
- sprintf(OUTPUT,"Copying from %s:%s\n",ip->server,sourcefile);
- CfLog(cfinform,OUTPUT,"");
-
- if (CopyReg(sourcefile,destfile,sourcestatbuf,deststatbuf,ip))
- {
- stat(destfile,&deststatbuf);
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
- AddCopyClasses(ip);
- }
-
- Debug2("Leaving ImageCopy\n");
- return;
- }
-
- if (S_ISFIFO (srcmode))
- {
- #ifdef HAVE_MKFIFO
- if (DONTDO)
- {
- Silent("%s: Make FIFO %s\n",VPREFIX,destfile);
- }
- else if (mkfifo (destfile,srcmode))
- {
- sprintf(OUTPUT,"Cannot create fifo `%s'", destfile);
- CfLog(cferror,OUTPUT,"mkfifo");
- return;
- }
-
- AddCopyClasses(ip);
- #endif
- }
- else
- {
- if (S_ISBLK (srcmode) || S_ISCHR (srcmode) || S_ISSOCK (srcmode))
- {
- if (DONTDO)
- {
- Silent("%s: Make BLK/CHR/SOCK %s\n",VPREFIX,destfile);
- }
- else if (mknod (destfile, srcmode, sourcestatbuf.st_rdev))
- {
- sprintf(OUTPUT,"Cannot create special file `%s'",destfile);
- CfLog(cferror,OUTPUT,"mknod");
- return;
- }
-
- AddCopyClasses(ip);
- }
- }
-
- if (S_ISLNK(srcmode))
- {
- if (cfreadlink(sourcefile,linkbuf,bufsize,ip) == -1)
- {
- sprintf(OUTPUT,"Can't readlink %s\n",sourcefile);
- CfLog(cferror,OUTPUT,"");
- Debug2("Leaving ImageCopy\n");
- return;
- }
-
- sprintf(OUTPUT,"Checking link from %s to %s\n",destfile,linkbuf);
- CfLog(cfverbose,OUTPUT,"");
-
- if (ip->linktype == 'a' && linkbuf[0] != '/') /* Not absolute path - must fix */
- {
- strcpy(VBUFF,sourcefile);
- ChopLastNode(VBUFF);
- AddSlash(VBUFF);
- strcat(VBUFF,linkbuf);
- strcpy(linkbuf,VBUFF);
- }
-
- switch (ip->linktype)
- {
- case 's':
- if (*linkbuf == '.')
- {
- succeed = RelativeLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- }
- else
- {
- succeed = LinkFiles(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- }
- break;
- case 'r':
- succeed = RelativeLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- break;
- case 'a':
- succeed = AbsoluteLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- break;
- default:
- printf("cfengine: internal error, link type was [%c] in ImageCopy\n",ip->linktype);
- return;
- }
-
- if (succeed)
- {
- lstat(destfile,&deststatbuf);
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
- AddCopyClasses(ip);
- }
- }
- }
- else
- {
- Debug("Destination file %s exists\n",destfile);
-
- if (! ip->force)
- {
- if (ip->size != cfnosize)
- {
- switch (ip->comp)
- {
- case '<': if (sourcestatbuf.st_size > ip->size)
- {
- sprintf(OUTPUT,"Source file %s is > %d bytes in copy\n",sourcefile,ip->size);
- CfLog(cfsilent,OUTPUT,"");
- return;
- }
- break;
-
- case '=': if (sourcestatbuf.st_size != ip->size)
- {
- sprintf(OUTPUT,"Source file %s is not %d bytes in copy\n",sourcefile,ip->size);
- CfLog(cfsilent,OUTPUT,"");
- return;
- }
- break;
-
- default: if (sourcestatbuf.st_size < ip->size)
- {
- Silent(OUTPUT,"Source file %s is < %d bytes in copy\n",sourcefile,ip->size);
- CfLog(cfsilent,OUTPUT,"");
- return;
- }
- break;;
- }
- }
-
- switch (ip->type)
- {
- case 'c': if (S_ISREG(deststatbuf.st_mode) && S_ISREG(srcmode))
- {
- ok_to_copy = CompareMD5CheckSums(sourcefile,destfile,ip,&sourcestatbuf,&deststatbuf);
- }
- else
- {
- Verbose("%s: Checksum comparison replaced by ctime: files not regular\n",VPREFIX);
- Verbose("%s: %s -> %s\n",VPREFIX,sourcefile,destfile);
- ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime);
- }
-
- if (ok_to_copy && strcmp(ip->action,"warn") == 0)
- {
- Verbose("%s: Image file %s has a wrong MD5 checksum\n",VPREFIX,destfile);
- Verbose("%s: (should be copy of %s)\n",VPREFIX,sourcefile);
- return;
- }
- break;
-
- case 'b': if (S_ISREG(deststatbuf.st_mode) && S_ISREG(srcmode))
- {
- ok_to_copy = CompareBinarySums(sourcefile,destfile,ip,&sourcestatbuf,&deststatbuf);
- }
- else
- {
- Verbose("%s: Byte comparison replaced by ctime: files not regular\n",VPREFIX);
- Verbose("%s: %s -> %s\n",VPREFIX,sourcefile,destfile);
- ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime);
- }
-
- if (ok_to_copy && strcmp(ip->action,"warn") == 0)
- {
- Verbose("%s: Image file %s has a wrong binary checksum\n",VPREFIX,destfile);
- Verbose("%s: (should be copy of %s)\n",VPREFIX,sourcefile);
- return;
- }
- break;
-
- case 'm': ok_to_copy = (deststatbuf.st_mtime < sourcestatbuf.st_mtime);
-
- if (ok_to_copy && strcmp(ip->action,"warn") == 0)
- {
- Verbose("%s: Image file %s out of date\n",VPREFIX,destfile);
- Verbose("%s: (should be copy of %s)\n", VPREFIX,sourcefile);
- return;
- }
- break;
-
- default: ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime);
-
- if (ok_to_copy && strcmp(ip->action,"warn") == 0)
- {
- Verbose("%s: Image file %s out of date\n",VPREFIX,destfile);
- Verbose("%s: (should be copy of %s)\n", VPREFIX,sourcefile);
- return;
- }
- break;
- }
- }
-
-
- if ((S_ISDIR(deststatbuf.st_mode) && ! S_ISDIR(sourcestatbuf.st_mode)) ||
- (S_ISREG(deststatbuf.st_mode) && ! S_ISREG(sourcestatbuf.st_mode)) ||
- (S_ISBLK(deststatbuf.st_mode) && ! S_ISBLK(sourcestatbuf.st_mode)) ||
- (S_ISCHR(deststatbuf.st_mode) && ! S_ISCHR(sourcestatbuf.st_mode)) ||
- (S_ISSOCK(deststatbuf.st_mode) && ! S_ISSOCK(sourcestatbuf.st_mode)) ||
- (S_ISFIFO(deststatbuf.st_mode) && ! S_ISFIFO(sourcestatbuf.st_mode)) ||
- (S_ISLNK(deststatbuf.st_mode) && ! S_ISLNK(sourcestatbuf.st_mode)))
-
- {
- printf("%s: image exists but destination type is silly (file/dir/link doesn't match)\n",VPREFIX);
- printf("%s: source=%s, dest=%s\n",VPREFIX,sourcefile,destfile);
- return;
- }
-
- if ((ip->force) || ok_to_copy || S_ISLNK(sourcestatbuf.st_mode)) /* Always check links */
- {
- if (S_ISREG(srcmode))
- {
- sprintf(OUTPUT,"Updating image %s from master %s on %s\n",destfile,sourcefile,ip->server);
- CfLog(cfinform,OUTPUT,"");
-
- AddCopyClasses(ip);
-
- if (CopyReg(sourcefile,destfile,sourcestatbuf,deststatbuf,ip))
- {
- stat(destfile,&deststatbuf);
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
- }
-
- return;
- }
-
- if (S_ISLNK(sourcestatbuf.st_mode))
- {
- if (cfreadlink(sourcefile,linkbuf,bufsize,ip) == -1)
- {
- sprintf(OUTPUT,"Can't readlink %s\n",sourcefile);
- CfLog(cferror,OUTPUT,"");
- return;
- }
-
- sprintf(OUTPUT,"Checking link from %s to %s\n",destfile,linkbuf);
- CfLog(cfverbose,OUTPUT,"");
-
- enforcelinks = ENFORCELINKS;
- ENFORCELINKS = true;
-
- switch (ip->linktype)
- {
- case 's':
- if (*linkbuf == '.')
- {
- succeed = RelativeLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- }
- else
- {
- succeed = LinkFiles(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- }
- break;
- case 'r':
- succeed = RelativeLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- break;
- case 'a':
- succeed = AbsoluteLink(destfile,linkbuf,NULL,NULL,NULL,true,&empty);
- break;
- default:
- printf("cfengine: internal error, link type was [%c] in ImageCopy\n",ip->linktype);
- return;
- }
-
- if (succeed)
- {
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
- }
- ENFORCELINKS = enforcelinks;
- }
- }
- else
- {
- CheckCopiedFile(destfile,ip->plus,ip->minus,fixall,ip->uid,ip->gid,&deststatbuf,&sourcestatbuf,NULL,ip->acl_aliases);
-
- Debug2("cfengine: image file is up to date: %s\n",destfile);
- }
- }
- }
-
- /*********************************************************************/
-
- cfstat(file,buf,ip)
-
- /* wrapper for network access */
-
- char *file;
- struct stat *buf;
- struct Image *ip;
-
- { int res;
-
- if (ip == NULL)
- {
- res = stat(file,buf);
- /* CheckForHoles(buf,ip); Don't need this if ip is NULL */
- return res;
- }
-
- if (strcmp(ip->server,"localhost") == 0)
- {
- res = stat(file,buf);
- CheckForHoles(buf,ip);
- return res;
- }
- else
- {
- return cf_rstat(file,buf,ip,"file");
- }
- }
-
- /*********************************************************************/
-
- cflstat(file,buf,ip)
-
- char *file;
- struct stat *buf;
- struct Image *ip;
-
- /* wrapper for network access */
-
- { int res;
-
- if (ip == NULL)
- {
- res = lstat(file,buf);
- /* CheckForHoles(buf,ip); Don't need this if ip is NULL */
- return res;
- }
-
- if (strcmp(ip->server,"localhost") == 0)
- {
- res = lstat(file,buf);
- CheckForHoles(buf,ip);
- return res;
- }
- else
- {
- /* read cache if possible */
- return cf_rstat(file,buf,ip,"link");
- }
- }
-
- /*********************************************************************/
-
- cfreadlink(sourcefile,linkbuf,buffsize,ip)
-
- char *sourcefile, *linkbuf;
- int buffsize;
- struct Image *ip;
-
- /* wrapper for network access */
-
- { struct cfstat *sp;
-
- if (strcmp(ip->server,"localhost") == 0)
- {
- return readlink(sourcefile,linkbuf,buffsize);
- }
-
- for (sp = ip->cache; sp != NULL; sp=sp->next)
- {
- if ((strcmp(ip->server,sp->cf_server) == 0) && (strcmp(sourcefile,sp->cf_filename) == 0))
- {
- if (sp->cf_readlink != NULL)
- {
- if (strlen(sp->cf_readlink)+1 > buffsize)
- {
- printf("%s: readlink value is too large in cfreadlink\n",VPREFIX);
- printf("%s: [%s]]n",VPREFIX,sp->cf_readlink);
- return -1;
- }
- else
- {
- bzero(linkbuf,buffsize);
- strcpy(linkbuf,sp->cf_readlink);
- return 0;
- }
- }
- }
- }
-
- return -1;
- }
-
- /*********************************************************************/
-
- CFDIR *cfopendir(name,ip)
-
- char *name;
- struct Image *ip;
-
- { CFDIR *cf_ropendir(),*returnval;
-
- if (strcmp(ip->server,"localhost") == 0)
- {
- if ((returnval = (CFDIR *)malloc(sizeof(CFDIR))) == NULL)
- {
- FatalError("Can't allocate memory in cfopendir()\n");
- }
-
- returnval->cf_list = NULL;
- returnval->cf_listpos = NULL;
- returnval->cf_dirh = opendir(name);
-
- if (returnval->cf_dirh != NULL)
- {
- return returnval;
- }
- else
- {
- free ((char *)returnval);
- return NULL;
- }
- }
- else
- {
- return cf_ropendir(name,ip);
- }
- }
-
- /*********************************************************************/
-
- struct cfdirent *cfreaddir(cfdirh,ip)
-
- CFDIR *cfdirh;
- struct Image *ip;
-
- /* We need this cfdirent type to handle the weird hack */
- /* used in SVR4/solaris dirent structures */
-
- { static struct cfdirent dir;
- struct dirent *dirp;
-
- bzero(dir.d_name,bufsize);
-
- if (strcmp(ip->server,"localhost") == 0)
- {
- dirp = readdir(cfdirh->cf_dirh);
-
- if (dirp == NULL)
- {
- return NULL;
- }
- strncpy(dir.d_name,dirp->d_name,bufsize);
- return &dir;
- }
- else
- {
- if (cfdirh->cf_listpos != NULL)
- {
- strncpy(dir.d_name,(cfdirh->cf_listpos)->name,bufsize);
- cfdirh->cf_listpos = cfdirh->cf_listpos->next;
- return &dir;
- }
- else
- {
- return NULL;
- }
- }
- }
-
- /*********************************************************************/
-
- cfclosedir(dirh)
-
- CFDIR *dirh;
-
- {
- if ((dirh != NULL) && (dirh->cf_dirh != NULL))
- {
- closedir(dirh->cf_dirh);
- }
-
- Debug("cfclosedir()\n");
- DeleteItemList(dirh->cf_list);
- free((char *)dirh);
- }
-
- /*********************************************************************/
- /* Level 2 */
- /*********************************************************************/
-
- CopyReg (source,dest,sstat,dstat,ip)
-
- char *source, *dest;
- struct stat sstat, dstat;
- struct Image *ip;
-
- { char backup[bufsize];
- char new[bufsize], *linkable;
- int remote = false, silent;
- #ifdef HAVE_UTIME_H
- struct utimbuf timebuf;
- #endif
-
- Debug2("CopyReg(%s,%s)\n",source,dest);
-
- if (DONTDO)
- {
- printf("%s: copy from %s to %s\n",VPREFIX,source,dest);
- return false;
- }
-
- /* Make an assoc array of inodes used to preserve hard links */
-
- linkable = CompressedArrayValue(ip->inode_cache,sstat.st_ino);
-
- if (sstat.st_nlink > 1) /* Preserve hard links, if possible */
- {
- if (CompressedArrayElementExists(ip->inode_cache,sstat.st_ino) && (strcmp(dest,linkable) != 0))
- {
- unlink(dest);
-
- silent = SILENT;
- SILENT = true;
-
- DoHardLink(dest,linkable,NULL);
-
- SILENT = silent;
- return true;
- }
- }
-
- if (strcmp(ip->server,"localhost") != 0)
- {
- Debug("This is a remote copy from server: %s\n",ip->server);
- remote = true;
- }
-
- strcpy(new,dest);
- strcat(new,CF_NEW);
-
- if (remote)
- {
- if (!CopyRegNet(source,new,ip,sstat.st_size))
- {
- return false;
- }
- }
- else
- {
- if (!CopyRegDisk(source,new,ip))
- {
- return false;
- }
-
- if (ip->stealth == 't')
- {
- #ifdef HAVE_UTIME_H
- timebuf.actime = sstat.st_atime;
- timebuf.modtime = sstat.st_mtime;
- utime(source,&timebuf);
- #endif
- }
- }
-
- Debug("CopyReg succeeded in copying to %s to %s\n",source,new);
-
- if (IMAGEBACKUP)
- {
- strcpy(backup,dest);
- strcat(backup,CF_SAVED);
-
- if (IsItemIn(VREPOSLIST,backup))
- {
- return true;
- }
-
- if (rename(dest,backup) == -1)
- {
- /* ignore */
- }
- }
-
- stat(new,&dstat);
-
- if (dstat.st_size != sstat.st_size)
- {
- sprintf(OUTPUT,"WARNING: new file %s seems to have been corrupted in transit, aborting!\n",new);
- CfLog(cfverbose,OUTPUT,"");
- if (rename(backup,dest) == -1)
- {
- /* ignore */
- }
- return false;
- }
-
- if (ip->secure)
- {
- Debug("Final verification of transmission...\n");
- if (CompareMD5CheckSums(source,new,ip,&sstat,&dstat))
- {
- sprintf(OUTPUT,"WARNING: new file %s seems to have been corrupted in transit, aborting!\n",new);
- CfLog(cfverbose,OUTPUT,"");
- if (rename(backup,dest) == -1)
- {
- /* ignore */
- }
- return false;
- }
- }
-
- if (rename(new,dest) == -1)
- {
- sprintf(OUTPUT,"Problem: could not install copy file as %s, directory in the way?\n",dest);
- CfLog(cferror,OUTPUT,"rename");
- rename(backup,dest);
- return false;
- }
-
- if (IMAGEBACKUP && Repository(backup))
- {
- unlink(backup);
- }
-
- return true;
- }
-
-
- /*********************************************************************/
-
- AddCopyClasses(ip)
-
- struct Image *ip;
-
- { char *sp;
- char currentitem[maxvarsize];
-
- Debug("Entering AddCopyClasses(%s)\n",ip->defines);
-
- for (sp = ip->defines; *sp != '\0'; sp++)
- {
- currentitem[0] = '\0';
-
- sscanf(sp,"%[^,:.]",currentitem);
-
- sp += strlen(currentitem)-1;
-
- AddClassToHeap(currentitem);
- }
- }
-
- /*********************************************************************/
- /* Level 3 */
- /*********************************************************************/
-
- RegisterHardLink(i,value,ip)
-
- int i;
- char *value;
- struct Image *ip;
-
- {
- if (!FixCompressedArrayValue(i,value,&(ip->inode_cache)))
- {
- /* Not root hard link, remove to preserve consistency */
- Verbose("Removing old hard link %s to preserve structure..\n",value);
- unlink(value);
- }
- }
-